package mylogx

import (
	"context"
	"encoding/json"
	"fmt"
	"runtime"
	"time"
)

// 日志级别类型
type Level int

const (
	Debug Level = iota
	Info
	Warn
	Error
	Fatal
)

var levelNames = [...]string{"DEBUG", "INFO", "WARN", "ERROR", "FATAL"}

// 日志字段类型
type Fields map[string]interface{}

// 日志条目结构
type Entry struct {
	Time      time.Time
	Level     Level
	Message   string
	FileLine  string
	RelatedID string
	TraceID   string
	Fields    Fields
}

// 日志接口定义
type Logger interface {
	Log(entry Entry)
}

// 默认控制台日志实现
type ConsoleLogger struct{}

func (l *ConsoleLogger) Log(entry Entry) {
	b, err := json.Marshal(entry)
	if err != nil {
		fmt.Println("json.Marshal failed, err:", err)
		return
	}
	fmt.Println(string(b))

	//fields := ""
	//for k, v := range entry.Fields {
	//	fields += fmt.Sprintf(" %s=%v", k, v)
	//}

	//fmt.Printf("[%s] %s %s traceID=%s relatedID=%s %s %s\n",
	//	levelNames[entry.Level],
	//	entry.Time.Format("2006-01-02 15:04:05.000"),
	//	entry.Message,
	//	entry.TraceID,
	//	entry.RelatedID,
	//	entry.FileLine,
	//	fields,
	//)
}

// 全局配置
var (
	defaultLogger Logger = &ConsoleLogger{}
	traceIDKey           = "traceID"
)

type SkipKey struct{}

func WithSkip(ctx context.Context, i int) context.Context {
	return context.WithValue(ctx, SkipKey{}, i)
}

// 获取调用者信息
func getCaller(skip int) string {
	_, file, line, ok := runtime.Caller(skip)
	if !ok {
		return ""
	}
	return fmt.Sprintf("%s:%d", file, line)
}

// 核心日志方法
func log(ctx context.Context, level Level, relatedID, msg string, fields ...Fields) {
	skip := 3
	if i, ok := ctx.Value(SkipKey{}).(int); ok {
		skip = i
	}

	entry := Entry{
		Time:      time.Now(),
		Level:     level,
		Message:   msg,
		FileLine:  getCaller(skip), // 跳过三层调用栈
		RelatedID: relatedID,
	}

	// 合并字段
	combinedFields := make(Fields)
	for _, f := range fields {
		for k, v := range f {
			combinedFields[k] = v
		}
	}
	entry.Fields = combinedFields

	// 处理 TraceID
	if ctx != nil {
		if id, ok := ctx.Value(traceIDKey).(string); ok {
			entry.TraceID = id
		}
	}
	if entry.TraceID == "" {
		entry.TraceID = generateTraceID() // 实现自己的ID生成逻辑
	}

	defaultLogger.Log(entry)
}

// 包级快捷方法
func DebugCtx(ctx context.Context, relatedID, msg string, fields ...Fields) {
	log(ctx, Debug, relatedID, msg, fields...)
}
func InfoCtx(ctx context.Context, relatedID string, msg ...any) {
	log(ctx, Info, relatedID, fmt.Sprint(msg), nil)
}
func InfoCtxW(ctx context.Context, relatedID, msg string, fields ...Fields) {
	log(ctx, Info, relatedID, msg, fields...)
}

func ErrCtx(ctx context.Context, relatedID string, msg ...any) {
	log(ctx, Error, relatedID, fmt.Sprint(msg), nil)
}
func ErrCtxW(ctx context.Context, relatedID, msg string, fields ...Fields) {
	log(ctx, Error, relatedID, msg, fields...)
}

// ... 其他级别方法 ...

// 不带Context的方法
func DebugLog(relatedID, msg string, fields ...Fields) {
	log(context.Background(), Debug, relatedID, msg, fields...)
}

func InfoLog(relatedID, msg string, fields ...Fields) {
	log(context.Background(), Info, relatedID, msg, fields...)
}
func ErrLog(relatedID, msg string, fields ...Fields) {
	log(context.Background(), Error, relatedID, msg, fields...)
}

// ... 其他不带Context的方法 ...

// 设置全局Logger
func SetLogger(logger Logger) {
	defaultLogger = logger
}

// 设置TraceID的Context Key
func SetTraceIDKey(key string) {
	traceIDKey = key
}

// 生成TraceID（示例实现）
func generateTraceID() string {
	return fmt.Sprintf("TRACE-%d", time.Now().UnixNano())
}

// 创建带TraceID的Context（新增方法）
func WithTraceID(parent context.Context, traceID ...string) context.Context {
	id := ""
	if len(traceID) > 0 && traceID[0] != "" {
		id = traceID[0]
	} else {
		id = generateTraceID()
	}
	return context.WithValue(parent, traceIDKey, id)
}

// 获取当前TraceID（新增方法）
func GetTraceID(ctx context.Context) string {
	if ctx == nil {
		return ""
	}
	if id, ok := ctx.Value(traceIDKey).(string); ok {
		return id
	}
	return ""
}
